/***********************************************************************************
 * Copyright (c) 2006-2021, Halo team
 *
 * SPDX-License-Identifier: GPLv3
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-10-05     Eywen        the first version
************************************************************************************/
#ifndef GCODE_H
#define GCODE_H

#include <stdint.h>
#include "../config_print.h"
#include "../ringbuff.h"
#include <stdbool.h>
#include "../fdm_printer.h"

#include <rtthread.h>
#include <serial.h>


/* gcode ringbuff最大长度 */
#define GCODE_RINGBUFF_LEN             (16u)
/* gcdeo命令号最大长度 */
#define GCODE_HEAD_NUMBER_MAX_LEN      (4u)
/* gcode参数数字最大长度  */
#define GCODE_PARA_NUMBER_LEN          (10u)
/* gcode参数最大个数 */
#define GCODE_FRAME_COUNT_MAX          (6u)
/* GCODE 字符串最大长度, 命令前缀1 + 命令序号长度 + (参数前缀 + 参数长度)*参数个数 */
#define GCODE_STR_MAX_LEN              (1 + (1 + GCODE_HEAD_NUMBER_MAX_LEN + \
                                        GCODE_PARA_NUMBER_LEN)*GCODE_FRAME_COUNT_MAX)

/* gcode二次解析线程的优先级 */
#define GCODE_HANDLE_THREAD_PRIORITY   (10)
#define GCODE_HANDLE_THREAD_TIMESLICE  (10u)
#define GCODE_HANDLE_THREAD_STACK_SIZE (2048)

#define GCODE_HANDLE_MOTION_TASK_ADD_TIMEOUT_MS (10u)

#define GCODE_REPY_OK_STR               "ok\r\n"
#define GCODE_REPY_ERR_STR              "gcode err\r\n"
#define GCODE_BUSY_STR                  "busy\r\n"

typedef struct gcode_para
{
    uint8_t head;
    char number[GCODE_PARA_NUMBER_LEN];
}gcode_para_t;

typedef struct gcode_head
{
    uint8_t comd;                              /* 命令头部标志 */
    char order[GCODE_HEAD_NUMBER_MAX_LEN];  /* 命令序号 */
}gcode_command_t;

typedef struct gcode{
    gcode_command_t comd;
    gcode_para_t para[GCODE_FRAME_COUNT_MAX];
    int para_cnt;
} gcode_t;


typedef struct gcode_handle_ops gcode_handle_ops_t;

typedef struct gcode_handle{
    ringbuff_t *handle_list;       /* 存放预提取后的gcode_t */

    struct rt_messagequeue *motion_gcode_mq;
    const gcode_handle_ops_t *ops;

    void *parent;

    rt_thread_t gcode_handle_thread_id;
}gcode_handle_t;

typedef struct fdm_printer fdm_printer_t;

typedef struct gcode_handle_map{
    gcode_command_t comd;                   /* gcode头部命令 */
    bool (*handle)(gcode_t *gcode, bool instantly, fdm_printer_t *fdm_printer);    /* gcode处理接口 */
}gcode_handle_map_t;

typedef struct gcode_handle_ops{
    bool (*init)(gcode_handle_t *handle);
    bool (*add_gcode)(gcode_handle_t *handle, gcode_t *gcode);
    bool (*task_full)(gcode_handle_t *handle);
    bool (*task_empty)(gcode_handle_t *handle);
    bool (*pop_task)(gcode_handle_t *handle, gcode_t *gcode);
    bool (*start)(gcode_handle_t *handle);
    void (*set_parent)(gcode_handle_t *handle, void *parent);
}gcode_handle_ops_t;

float str_to_float(char *str);

bool gcode_handle_register(gcode_handle_t *device);

#endif // GCODE_H
